package com.mf.ergate.dao;

import com.mf.framework.common.model.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * DAO通用实现
 * User: zhaoming
 * Date: 2016-06-24
 * To change this template use File | Settings | File Templates.
 **/
public class GenericDao<T> extends BaseDao<T> implements IDao<T>, IMapper{

    public Logger logger = LoggerFactory.getLogger(getClass());

    private static final String INSERT                          = "insert";                         //新增
    private static final String BATCH_INSERT                    = "batchInsert";                    //批量新增
    private static final String UPDATE_BY_PRIMARY_KEY           = "updateByPrimaryKey";             //根据主键修改
    private static final String UPDATE_BY_UNIQUE_NO             = "updateByUniqueNo";               //根据唯一编号修改
    private static final String DISCARD_BY_PRIMARY_KEY          = "discardByPrimaryKey";            //根据主键删除(物理)
    private static final String DISCARD_BY_UNIQUE_NO            = "discardByUniqueNo";              //根据唯一编号删除(物理)
    private static final String DISCARD_BY_PRIMARY_KEYS         = "discardByPrimaryKeys";           //根据主键批量删除(物理)
    private static final String DISCARD_BY_UNIQUE_NOS           = "discardByUniqueNos";             //根据唯一编号批量删除(物理)
    private static final String DELETE_BY_PRIMARY_KEY           = "deleteByPrimaryKey";             //根据主键删除(逻辑)
    private static final String DELETE_BY_UNIQUE_NO             = "deleteByUniqueNo";               //根据唯一编号删除(逻辑)
    private static final String DELETE_BY_PRIMARY_KEYS          = "deleteByPrimaryKeys";            //根据主键批量删除(逻辑)
    private static final String DELETE_BY_UNIQUE_NOS            = "deleteByUniqueNos";              //根据唯一编号批量删除(逻辑)
    private static final String SELECT_BY_PRIMARY_KEY           = "selectByPrimaryKey";             //根据主键查询
    private static final String SELECT_BY_UNIQUE_NO             = "selectByUniqueNo";               //根据唯一编号查询
    private static final String SELECT_BY_CONDITION             = "selectByCondition";              //根据条件查询
    private static final String SELECT_COUNT                    = "selectCount";                    //根据条件查询数量
    private static final String SELECT_PAGE                     = "selectPage";                     //根据分页条件查询

    /**
     * 新增实体对象
     * @param entity 实体对象
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean insert(T entity){
        return this.insert(this.getStatement(INSERT), entity);
    }

    /**
     * 批量新增实体对象
     * @param entities 实体对象列表
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean batchInsert(List<T> entities){
        return this.insert(this.getStatement(BATCH_INSERT), entities);
    }

    /**
     * 根据主键修改实体对象
     * @param entity 实体对象
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean updateByPrimaryKey(T entity){
        return this.update(this.getStatement(UPDATE_BY_PRIMARY_KEY), entity);
    }

    /**
     * 根据唯一编号修改实体对象
     * @param entity 实体对象
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean updateByUniqueNo(T entity){
        //修改实体
        return this.update(this.getStatement(UPDATE_BY_UNIQUE_NO), entity);
    }

    /**
     * 根据主键删除实体对象(物理删除)
     * @param id 主键
     * @return 执行结果 (true:成功; false:失败)
     */
    @SuppressWarnings("ALL")
    public Boolean discardByPrimaryKey(Long id){
        return this.discard(this.getStatement(DISCARD_BY_PRIMARY_KEY), id);
    }

    /**
     * 根据唯一编号删除实体对象(物理删除)
     * @param uniqueNo 唯一编号
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean discardByUniqueNo(String uniqueNo){
        return this.discard(this.getStatement(DISCARD_BY_UNIQUE_NO), uniqueNo);
    }

    /**
     * 根据主键批量删除实体对象(物理删除)
     * @param entities 实体对象列表
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean discardByPrimaryKeys(List<T> entities){
        return this.discard(this.getStatement(DISCARD_BY_PRIMARY_KEYS), entities);
    }

    /**
     * 根据唯一编号批量删除实体对象(物理删除)
     * @param entities 实体对象列表
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean discardByUniqueNos(List<T> entities){
        return this.discard(this.getStatement(DISCARD_BY_UNIQUE_NOS), entities);
    }

    /**
     * 根据主键删除实体对象(逻辑删除)
     * @param entity 实体对象
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean deleteByPrimaryKey(T entity){
        return this.update(this.getStatement(DELETE_BY_PRIMARY_KEY), entity);
    }

    /**
     * 根据唯一编号删除实体对象(逻辑删除)
     * @param entity 实体对象
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean deleteByUniqueNo(T entity){
        return this.update(this.getStatement(DELETE_BY_UNIQUE_NO), entity);
    }

    /**
     * 根据主键批量删除实体对象(逻辑删除)
     * @param entities 实体对象列表
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean deleteByPrimaryKeys(List<T> entities){
        return this.deleteByIds(this.getStatement(DELETE_BY_PRIMARY_KEYS), entities);
    }

    /**
     * 根据唯一编号批量删除实体对象(逻辑删除)
     * @param entities 实体对象列表
     * @return 执行结果 (true:成功; false:失败)
     */
    public Boolean deleteByUniqueNos(List<T> entities){
        return this.deleteByUniqueNos(this.getStatement(DELETE_BY_UNIQUE_NOS), entities);
    }

    /**
     * 根据主键查询实体对象
     * @param id 主键
     * @return 实体对象
     */
    public T selectByPrimaryKey(Long id){
        return this.selectOne(this.getStatement(SELECT_BY_PRIMARY_KEY), id);
    }

    /**
     * 根据唯一编号查询实体对象
     * @param uniqueNo 唯一编号
     * @return 实体对象
     */
    public T selectByUniqueNo(String uniqueNo){
        return this.selectOne(this.getStatement(SELECT_BY_UNIQUE_NO), uniqueNo);
    }

    /**
     * 根据条件查询实体对象列表
     * @param entity 实体对象
     * @return 实体对象列表
     */
    public List<T> selectByCondition(Object entity) {
        return this.selectList(this.getStatement(SELECT_BY_CONDITION), entity);
    }

    /**
     * 根据条件查询实体对象数量
     * @param entity 实体对象
     * @return 实体对象列表
     */
    public Integer selectCount(Object entity) {
        return this.selectCount(this.getStatement(SELECT_COUNT), entity);
    }

    /**
     * 分页查询实体对象列表
     * @param page 分页实体
     * @param entity 实体对象
     * @return 实体对象列表
     */
	public Page<T> selectPage(Page page, Object entity){
        return this.selectPage(this.getStatement(SELECT_PAGE), this.getStatement(SELECT_COUNT), page, entity);
    }

    /**
     * 获取映射文件命名空间 ，默认使用DAO实例的类名
     * @return 映射文件命名空间
     */
    public String getNamespace(){
        // 本系统将DAO接口作为命名空间
        Class<?>[] obj = this.getClass().getInterfaces();
        // 如果DAO没有继承接口
        if (obj == null || obj.length < 1) {
            throw new RuntimeException("DAO实现类需要实现接口，同时该接口名作为Mapper命名空间");
        }
        return obj[0].getName();
    }

    /**
     * 获取SQL语句在映射文件中的id
     * @return SQL语句在映射文件中的id
     */
    public String getStatement(String statementKey){
        return this.getNamespace() + "." + statementKey;
    }
}
